#include "spi_x.h"
#include <string.h>

#include "m_config.h"

// #define PIN_NUM_MISO 17 // pin 27
// #define PIN_NUM_MOSI 10 
// #define PIN_NUM_CLK 9  
// #define PIN_NUM_MISO 19 
// #define PIN_NUM_MOSI 23 
// #define PIN_NUM_CLK 18  
// #define SPI_DATA_OUT_CS GPIO_NUM_16 // Pin 25
// according to esp32-pico-d4_datasheet

#ifdef USE_SPI_DATA_OUT


    #define PIN_NUM_MOSI 10 // pin 29
    #define PIN_NUM_CLK 9  // pin 28
    #define PIN_NUM_MISO 19 // pin 38
    #define SPI_DATA_OUT_CS GPIO_NUM_22 // Pin 39

#endif


#ifdef USE_SPI_DATA_OUT

#define GPIO_OUTPUT_PIN_SEL ((1ULL << SPI_DATA_OUT_CS) )

spi_device_handle_t spi_data_out;

void spi2_config(void)
{
    esp_err_t ret;
    //    spi_device_handle_t handle;

    // Configuration for the SPI bus
    spi_bus_config_t buscfg;
    memset(&buscfg, 0, sizeof(spi_bus_config_t));
    buscfg.mosi_io_num = PIN_NUM_MOSI;
    buscfg.miso_io_num = PIN_NUM_MISO;
    buscfg.sclk_io_num = PIN_NUM_CLK;

    // Configuration for the SPI device on the other side of the bus
    spi_device_interface_config_t devcfg = {
        .clock_speed_hz = 4000000, // 4M 
        // .clock_speed_hz = 1000000, // 4M 

        // Note that I use spi speed of 4M, which is slow enough so in the ads1299 driver I do not need to worry about the tSDECODE problem.
        .mode = 0,
        .spics_io_num = -1,
        .queue_size = 4,
        // .command_bits = 0,
        // .address_bits = 0,
    };

    // Initialize the SPI bus
    // ret = spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_DISABLED);    
    ret = spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO);
    ESP_ERROR_CHECK(ret);

    ret = spi_bus_add_device(SPI3_HOST, &devcfg, &spi_data_out);
    ESP_ERROR_CHECK(ret);

/**/

    gpio_config_t io_conf = {
        .pin_bit_mask = (1ULL << SPI_DATA_OUT_CS),
        .mode = GPIO_MODE_INPUT_OUTPUT,
        .intr_type = GPIO_INTR_DISABLE,
        .pull_down_en = 0,
        .pull_up_en = true};
    gpio_config(&io_conf);


    // gpio_config_t io_conf = {
    //     .pin_bit_mask = GPIO_OUTPUT_PIN_SEL,
    //     .mode = GPIO_MODE_INPUT_OUTPUT,
    //     .intr_type = GPIO_INTR_DISABLE,
    //     .pull_down_en = 0,
    //     .pull_up_en = true};
    // gpio_config(&io_conf);


    gpio_set_level(SPI_DATA_OUT_CS, 1);

}

static void cs_low(void){
    gpio_set_level(SPI_DATA_OUT_CS, 0);
}

static void cs_high(void){
    gpio_set_level(SPI_DATA_OUT_CS, 1);
}

int spi_data_out_send(const uint8_t *p_tx_buffer, uint16_t len){
    cs_low();
    esp_err_t ret;

    spi_transaction_t spi_t;
    memset(&spi_t, 0, sizeof(spi_t)); // Zero out the transaction
    spi_t.length = 8*len;
    spi_t.tx_buffer = p_tx_buffer;

    ret = spi_device_polling_transmit(spi_data_out, &spi_t);
    assert(ret == ESP_OK);

    cs_high();
    return ret;
}

#endif




